//
// DebugFrame.h
// ============
// Provide a base class for derived class to operate DebugManager more
// easily and enable internal leak detection feature.
//
// Copyright (C) Aura Development Team, 2012 - 2013.
//

#ifndef __DEBUG_FRAME_H__
#define __DEBUG_FRAME_H__

#include "SevenHeader.h"
#include "DebugManager.h"

// Print a message with DebugFrame
#define LOG_WRITE(message, ...) \
	(_getDebugManager() && _getDebugManager()->print(TEXT(__FILE__), __LINE__, TEXT(__FUNCTION__), message, __VA_ARGS__))

#define ADD_BRACKET2(text)	text ## L"[]"
#define ADD_BRACKET(text)	ADD_BRACKET2(text)

#if  defined _DEBUG && defined _INTERNAL_LEAK_DETECTION
// Attach this code clip into class declaration to enable memory check.
# define INTERNAL_MEMORY_CHECK(object_name) \
	static void *operator new(size_t size, const std::nothrow_t &, \
		wchar_t *filename, int line) { \
			void *p = ::operator new(size, std::nothrow); \
			if(p != NULL) { \
				CDebugManager::_onAllocation(size, object_name, \
					filename, line, p); \
			} \
			return p; \
	} \
	static void *operator new(size_t size, const std::nothrow_t &) { \
		void *p = ::operator new(size, std::nothrow); \
		if(p != NULL) { \
			CDebugManager::_onAllocation(size, object_name, \
				TEXT(__FILE__), __LINE__, p); \
		} \
		return p; \
	} \
	static void *operator new[](size_t size, const std::nothrow_t &, \
		wchar_t *filename, int line) { \
			void *p = ::operator new[](size, std::nothrow); \
			if(p != NULL) { \
				CDebugManager::_onAllocation(size, ADD_BRACKET(object_name), \
					filename, line, p); \
			} \
			return p; \
	} \
	static void *operator new[](size_t size, const std::nothrow_t &) { \
			void *p = ::operator new[](size, std::nothrow); \
			if(p != NULL) { \
				CDebugManager::_onAllocation(size, ADD_BRACKET(object_name), \
					TEXT(__FILE__), __LINE__, p); \
			} \
			return p; \
	} \
	static void operator delete(void *p) { \
		CDebugManager::_onDeallocation(p); \
		::operator delete(p); \
	} \
	static void operator delete[](void *p) { \
		CDebugManager::_onDeallocation(p); \
		::operator delete(p); \
	}
#else
# define INTERNAL_MEMORY_CHECK(object_name)
#endif // _DEBUG && _INTERNAL_LEAK_DETECTION


class CDebugFrame
{
private:
	CDebugManager *_debugger;

public:
	CDebugFrame(void) 
	{
		_debugger = CDebugManager::getInstance();
	}
	CDebugFrame(const CDebugFrame &frame) 
	{
		_debugger = CDebugManager::getInstance();
	}
	virtual ~CDebugFrame(void) {};

	// Assignment operator
	CDebugFrame &operator=(const CDebugFrame &frame)
	{
		_debugger = CDebugManager::getInstance();
		return *this;
	}

protected:
	CDebugManager *_getDebugManager(void) const
	{
		return _debugger;
	}
};

#endif // __DEBUG_FRAME_H__